package com.zhejiangzhengyuan.municipal_common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhejiangzhengyuan.municipal_common.entity.*;
import com.zhejiangzhengyuan.municipal_common.entity.dto.FileDto;
import com.zhejiangzhengyuan.municipal_common.entity.dto.MaintenanceManageDto;
import com.zhejiangzhengyuan.municipal_common.entity.vo.MaintenanceChartVo;

import com.zhejiangzhengyuan.municipal_common.entity.vo.MaintenanceManageVo;
import com.zhejiangzhengyuan.municipal_common.entity.vo.MaintenanceRecordFuzzySelectVo;
import com.zhejiangzhengyuan.municipal_common.mapper.*;
import com.zhejiangzhengyuan.municipal_common.response.ResponseVo;
import com.zhejiangzhengyuan.municipal_common.service.MaintenanceRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhejiangzhengyuan.municipal_common.utils.ConstantUtil;
import com.zhejiangzhengyuan.municipal_common.utils.FileDuplicateCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zhejiangzhengyuan.municipal_common.utils.excelFileUtils.FileUtil;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;

import static com.zhejiangzhengyuan.municipal_common.utils.DateFormatUtil.*;
import static com.zhejiangzhengyuan.municipal_common.utils.StaticConstants.WAY_MODULE;

/**
 * 该表不作为交互业务直接写入，而是由道路或桥梁养护任务完成时，由养护任务内容数据进行同步，并关联上养护目标（桥梁或道路）；
 * 养护记录虽然存在与道路或桥梁表的关联，但是不存在直接的物理外键关系，所以这里没有外键约束 服务实现类
 *
 * @author linju
 * @since 2019-11-22
 */
@Service
@Slf4j
public class MaintenanceRecordServiceImpl
    extends ServiceImpl<MaintenanceRecordMapper, MaintenanceRecord>
    implements MaintenanceRecordService {
  @Autowired private MaintenanceRecordFileMappingMapper maintenanceRecordFileMappingMapper;
  @Autowired private MaintenanceRecordMapper maintenanceRecordMapper;
  @Autowired private FileMapper fileMapper;
  @Autowired private RoadGisMapper roadGisMapper;
  @Autowired private BridgeGisMapper bridgeGisMapper;
  @Autowired private FileDuplicateCode fileDuplicateCode;

  private String dayPattern = "yyyy-MM-dd";

  @Override
  public Long addMaintenance(MaintenanceRecord maintenanceRecord) {
    if (maintenanceRecordMapper.insert(maintenanceRecord) > 0) {
      return maintenanceRecord.getId();
    }
    return null;
  }

  @Override
  public int updateMaintenance(MaintenanceManageDto dto) {
    MaintenanceRecord maintenanceRecord = new MaintenanceRecord();
    maintenanceRecord.setId(dto.getId());
    maintenanceRecord.setUpdateTime(timeFormat(System.currentTimeMillis()));
    maintenanceRecord.setEndTime(dto.getEndTime());
    maintenanceRecord.setStartTime(dto.getStartTime());
    maintenanceRecord.setEventContext(dto.getEventContext());
    maintenanceRecord.setMaintenanceUnit(dto.getMaintenanceUnit());
    maintenanceRecord.setReason(dto.getReason());
    maintenanceRecord.setRemark(dto.getRemark());
    maintenanceRecord.setTargetId(dto.getTargetId());
    maintenanceRecord.setResult(dto.getResult());
    maintenanceRecord.setUsername(dto.getUsername());
    String link = dto.getLinkList();
    String[] linkList = FileUtil.getUrlsByRequest(link);
    if (maintenanceRecordMapper.updateById(maintenanceRecord) > 0) {
      // 删除文件
      if (linkList != null) {
        for (String s : linkList) {
          QueryWrapper<File> fileQueryWrapper = new QueryWrapper<>();
          fileQueryWrapper.eq("link", s);
          File file = fileMapper.selectOne(fileQueryWrapper);
          if (file!=null) {
            QueryWrapper<MaintenanceRecordFileMapping> fileMappingQueryWrapper = new QueryWrapper<>();
            fileMappingQueryWrapper.eq("file_id", file.getId());
            if (maintenanceRecordFileMappingMapper.delete(fileMappingQueryWrapper) > 0) {
              fileMapper.deleteById(file.getId());
              try {
                FileUtil.removeFile(s);
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
          }
        }
      }
    }

    return 1;
  }

  // 查询养护记录
  @Override
  public IPage<MaintenanceManageVo> selectAllMaintenanceRecord(Page<MaintenanceManageVo> page) {
    Page<MaintenanceManageVo> maintenanceManageVoPage =
        maintenanceRecordMapper.selectMaintenanceManageVoPage(page);
    List<MaintenanceManageVo> records = maintenanceManageVoPage.getRecords();
    for (MaintenanceManageVo maintenanceManageVo : records) {
      List<String> fileList = fileMapper.selectByMid(maintenanceManageVo.getId());
      maintenanceManageVo.setLink(fileList);
      String targetId = maintenanceManageVo.getTargetId();
      QueryWrapper<BridgeGis> bridgeGisQueryWrapper = new QueryWrapper<>();
      bridgeGisQueryWrapper.eq("code", targetId);
      BridgeGis bridgeGis = bridgeGisMapper.selectOne(bridgeGisQueryWrapper);
      if (bridgeGis != null) {
        maintenanceManageVo.setTargetName(bridgeGis.getName());
      }
      QueryWrapper<RoadGis> roadGisQueryWrapper = new QueryWrapper<>();
      QueryWrapper<RoadGis> code = roadGisQueryWrapper.eq("code", targetId);
      RoadGis roadGis = roadGisMapper.selectOne(code);
      if (roadGis != null) {
        maintenanceManageVo.setTargetName(roadGis.getName());
      }
    }
    return maintenanceManageVoPage;
  }

  // 根据id删除文件记录和相关联的文件表和文件
  @Override
  public Boolean removeById(Long id) {
    QueryWrapper<MaintenanceRecordFileMapping> wrapper = new QueryWrapper<>();
    QueryWrapper<MaintenanceRecordFileMapping> maintenance_record_id =
        wrapper.eq("maintenance_record_id", id);
    List<MaintenanceRecordFileMapping> maintenanceRecordFileMappings =
        maintenanceRecordFileMappingMapper.selectList(maintenance_record_id);
    if (maintenanceRecordFileMappingMapper.delete(maintenance_record_id) < 1) {
      return false;
    }
    for (MaintenanceRecordFileMapping maintenanceRecordFileMapping :
        maintenanceRecordFileMappings) {
      Long fileId = maintenanceRecordFileMapping.getFileId();
      File file = fileMapper.selectById(fileId);
      String link = file.getLink();
      try {
        FileUtil.removeFile(link);
      } catch (IOException e) {
        e.printStackTrace();
      }
      fileMapper.deleteById(fileId);
    }
    // 删除文件
    maintenanceRecordMapper.deleteById(id);

    return true;
  }

  // 根据id删除文件记录和相关联的文件表和文件写
  @Override
  public Boolean removeByIds(List<Long> idList) {
    for (Long id : idList) {
      QueryWrapper<MaintenanceRecordFileMapping> wrapper = new QueryWrapper<>();
      QueryWrapper<MaintenanceRecordFileMapping> maintenance_record_id =
          wrapper.eq("maintenance_record_id", id);
      List<MaintenanceRecordFileMapping> maintenanceRecordFileMappings =
          maintenanceRecordFileMappingMapper.selectList(maintenance_record_id);
      maintenanceRecordFileMappingMapper.delete(maintenance_record_id);
      for (MaintenanceRecordFileMapping maintenanceRecordFileMapping :
          maintenanceRecordFileMappings) {
        Long fileId = maintenanceRecordFileMapping.getFileId();
        File file = fileMapper.selectById(fileId);
        String link = file.getLink();
        fileMapper.deleteById(fileId);
        try {
          FileUtil.removeFile(link);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      maintenanceRecordMapper.deleteById(id);
    }
    return true;
  }

  // 道路桥梁封装后姓名的模糊查询
  @Override
  public List<MaintenanceRecordFuzzySelectVo> fuzzySelectByMaintenanceObject(String str) {
    QueryWrapper<BridgeGis> wrapper = new QueryWrapper<>();
    QueryWrapper<BridgeGis> bridgeGisQueryWrapper = wrapper.like("name", str);
    QueryWrapper<RoadGis> gisQueryWrapper = new QueryWrapper<>();
    QueryWrapper<RoadGis> roadGisQueryWrapper = gisQueryWrapper.like("name", str);
    List<BridgeGis> bridgeGis = bridgeGisMapper.selectList(bridgeGisQueryWrapper);
    List<RoadGis> roadGis = roadGisMapper.selectList(roadGisQueryWrapper);
    List<MaintenanceRecordFuzzySelectVo> maintenanceRecordFuzzySelectVos = new ArrayList<>();
    for (BridgeGis bridgeGi : bridgeGis) {
      MaintenanceRecordFuzzySelectVo maintenanceRecordFuzzySelectVo =
          new MaintenanceRecordFuzzySelectVo();
      String id = bridgeGi.getCode();
      String name = bridgeGi.getName();
      maintenanceRecordFuzzySelectVo.setTargetId(id);
      maintenanceRecordFuzzySelectVo.setName(name);
      maintenanceRecordFuzzySelectVos.add(maintenanceRecordFuzzySelectVo);
    }
    for (RoadGis roadGi : roadGis) {
      MaintenanceRecordFuzzySelectVo maintenanceRecordFuzzySelectVo =
          new MaintenanceRecordFuzzySelectVo();
      String id = roadGi.getCode();
      String name = roadGi.getName();
      maintenanceRecordFuzzySelectVo.setTargetId(id);
      maintenanceRecordFuzzySelectVo.setName(name);
      maintenanceRecordFuzzySelectVos.add(maintenanceRecordFuzzySelectVo);
    }
    return maintenanceRecordFuzzySelectVos;
  }

  @Override
  public int updateMaintenanceRecordFile(FileDto dto) {
    MultipartFile multipartFile = dto.getFile();
    Long id = dto.getId();
    if (multipartFile == null || id == null) {
      return 0;
    }
    if (Objects.isNull(maintenanceRecordMapper.selectById(id))) {
      return 0;
    }
    File file = new File();
    if (fileDuplicateCode.insertFileDuplicateCode(file, multipartFile, WAY_MODULE) > 0) {
      MaintenanceRecordFileMapping maintenanceRecordFileMapping =
          new MaintenanceRecordFileMapping();
      maintenanceRecordFileMapping.setCreateTime(timeFormat(System.currentTimeMillis()));
      maintenanceRecordFileMapping.setUpdateTime(timeFormat(System.currentTimeMillis()));
      maintenanceRecordFileMapping.setMaintenanceRecordId(id);
      maintenanceRecordFileMapping.setFileId(file.getId());
      maintenanceRecordFileMappingMapper.insert(maintenanceRecordFileMapping);
    }
    return 1;
  }

  public ResponseVo maintenanceRecordChart(String startTime, String endTime) {
    try {
      // 获取起始时间timestamp
      long startTimestamp = getTimeByString(dayPattern, startTime);
      long endTimestamp = getTimeByString(dayPattern, endTime);
      // 若时间小于等于3天 时间粒度为小时，否则按日返回;计算日期间隔 需+1
      int timeInterval = (int) ((endTimestamp - startTimestamp) / (24 * 60 * 60 * 1000) + 1);
      if (timeInterval > 3) {
        return ResponseVo.successWithData(getChartVoByDay(startTimestamp, timeInterval));
      } else {
        return ResponseVo.successWithData(getChartVoByHours(startTimestamp, timeInterval));
      }
    } catch (ParseException e) {
      e.printStackTrace();
      return new ResponseVo(ConstantUtil.HTTP_CODE.CLIENT_PARAM_ERROR, "请提供标准日期，格式为 年-月-日");
    }
  }

  // 根据天返回数据
  private List<MaintenanceChartVo> getChartVoByDay(long startTimestamp, int timeInterval) {
    // 获取格式化的开始时间
    Calendar date = calendarFormat(startTimestamp);
    List<MaintenanceChartVo> results = new ArrayList<>();
    long startStamp;
    //        long endStamp = 0;
    //        MaintenanceChartVo maintenanceChartVo;
    for (int i = 0; i < timeInterval; i++) {
      // 获取起始时间
      startStamp = date.getTimeInMillis();
      // 获取后一天的起始时间减一 为当天的结束时间
      date.add(Calendar.DATE, 1);
      results.add(formatChartVo(dayPattern, startStamp, date));
    }
    return results;
  }

  // 根据小时返回数据
  private List<MaintenanceChartVo> getChartVoByHours(long startTimestamp, int timeInterval) {
    // 获取格式化的开始时间
    Calendar date = calendarFormat(startTimestamp);
    List<MaintenanceChartVo> results = new ArrayList<>();
    long startStamp;
    //        MaintenanceChartVo maintenanceChartVo;
    for (int i = 0; i < timeInterval; i++) {
      // 一天内for24次 取每天24小时的数据
      for (int j = 0; j < 24; j++) {
        // 获取起始时间
        startStamp = date.getTimeInMillis();
        // 封装每个小时的返回值
        date.add(Calendar.HOUR_OF_DAY, 1);
        String hourPattern = "yyyy-MM-dd HH:mm:ss";
        results.add(formatChartVo(hourPattern, startStamp, date));
      }
    }
    return results;
  }

  private MaintenanceChartVo formatChartVo(String pattern, long startStamp, Calendar date) {
    // 区分开 并不是返回time的格式，该格式供pgSql匹配timestamp使用
    String hourPattern = "yyyy-MM-dd HH:mm:ss";
    long endStamp = date.getTimeInMillis() - 1;
    MaintenanceChartVo maintenanceChartVo = new MaintenanceChartVo();
    maintenanceChartVo.setTime(getStringByTime(pattern, startStamp));
    int i =
        maintenanceRecordMapper.selectChartByTimestamp(
            getStringByTime(hourPattern, startStamp), getStringByTime(hourPattern, endStamp));
    maintenanceChartVo.setCounts(i);
    // 获得data数据
    return maintenanceChartVo;
  }
}
